<template>
  <BasicDrawer
    v-bind="$attrs"
    @register="registerDrawer"
    showFooter
    :title="getTitle"
    width="500px"
    @ok="handleSubmit"
  >
    <BasicForm @register="registerForm">
      <template #status="{ model, field }">
        <RadioGroup
          v-model:value="model[field]"
          option-type="button"
          button-style="solid"
          :options="options"
        />
      </template>
      <template #menu>
        <BasicTree
          :checkedKeys="checkedKeys"
          :treeData="treeData"
          checkable
          toolbar
          @check="handleCheck"
          :fieldNames="{ key: 'id', title: 'menuName' }"
          title="菜单分配"
        />
      </template>
    </BasicForm>
  </BasicDrawer>
</template>
<script lang="ts">
  import { defineComponent, ref, computed, unref } from 'vue';
  import { BasicForm, useForm } from '/@/components/Form/index';
  import { formSchema } from './role.data';
  import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  import { BasicTree } from '/@/components/Tree';
  import { getSysMenuWithTreeApi } from '/@/api/modules/system/menu';
  import { RadioGroup } from 'ant-design-vue';
  import {
    getSysMenuByRoleIdWithOptionTreeApi,
    postAssignMenuApi,
    postRoleApi,
  } from '/@/api/modules/system/role';
  import { useMessage } from '/@/hooks/web/useMessage';
  export default defineComponent({
    name: 'RoleDrawer',
    components: { BasicDrawer, BasicForm, BasicTree, RadioGroup },
    emits: ['success', 'register'],
    setup(_, { emit }) {
      const isUpdate = ref(true);
      const treeData = ref<any>([]);
      const rowId = ref();
      const checkedKeys = ref<any>([]);
      const halfCheckedKeys = ref<any>([]);
      const parentIds = ref(new Set());
      const treeCheck = ref(false);
      const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
        labelWidth: 90,
        baseColProps: { span: 24 },
        schemas: formSchema,
        showActionButtonGroup: false,
      });
      const options = [
        { label: '启用', value: '1' },
        { label: '停用', value: '0' },
      ];
      const { createMessage, createConfirm } = useMessage();
      const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
        resetFields();
        setDrawerProps({ confirmLoading: false });
        rowId.value = data.record.id;
        const roleMenuList = (await getSysMenuByRoleIdWithOptionTreeApi({
          roleId: rowId.value,
        })) as any;
        // 找出菜单的所有父节点ID
        parentIds.value = new Set(
          roleMenuList.filter((item) => item.parentId !== null).map((item) => item.parentId),
        );
        console.log(parentIds.value);
        // 因为antd树插件勾选父节点会导致所有子节点选中,所以过滤所有父节点
        checkedKeys.value = roleMenuList
          .filter((item) => !parentIds.value.has(item.id))
          .map((item) => item.id);
        console.log(checkedKeys.value);
        // 需要在setFieldsValue之前先填充treeData，否则Tree组件可能会报key not exist警告
        if (unref(treeData).length === 0) {
          treeData.value = await getSysMenuWithTreeApi();
        }
        isUpdate.value = !!data?.isUpdate;

        if (unref(isUpdate)) {
          setFieldsValue({
            ...data.record,
          });
        }
      });

      const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));

      async function handleSubmit() {
        try {
          const values = await validate();
          if (checkedKeys.value.length > 0) {
            createConfirm({
              iconType: 'warning',
              title: '提示',
              content: '确认分配菜单？',
              onOk: async () => {
                setDrawerProps({ confirmLoading: true });
                // 如果没有check过，半选节点是拿不到的，只能通过预先设置的pidSet获取
                const menuIds = unref(treeCheck)
                  ? [...checkedKeys.value, ...halfCheckedKeys.value]
                  : [...checkedKeys.value, ...Array.from(parentIds.value)];
                await postAssignMenuApi({
                  menuIds: menuIds,
                  roleId: rowId.value,
                });
                createMessage.success('分配成功！');
                closeDrawer();
                emit('success');
              },
            });
          } else {
            setDrawerProps({ confirmLoading: true });
            await postRoleApi(values);
            closeDrawer();
            emit('success');
          }
        } finally {
          setDrawerProps({ confirmLoading: false });
        }
      }

      // 树节点选中事件
      function handleCheck(keys, e) {
        console.log('onChecked', keys, e);
        if (!unref(treeCheck)) {
          treeCheck.value = true;
        }
        checkedKeys.value = keys;
        halfCheckedKeys.value = e.halfCheckedKeys;
      }

      return {
        registerDrawer,
        registerForm,
        getTitle,
        handleSubmit,
        treeData,
        checkedKeys,
        handleCheck,
        options,
      };
    },
  });
</script>
